/*******************************************************************
 * author   :  Charlies-ls
 * Date     :  2021-09-26
 * Copyright (c) 2021. artestplay@outlook.com. All Rights Reserved.
 *******************************************************************/
#include "ax_string.h"
#include "com.h"
#include "ax_printf.h"
#include "ax_vector.h"
#include "ax_vector.h"
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>

#define  MAX_FORMAT_BUFFER 1024


struct ax_string
{
    char*   data;
    size_t  length;
    size_t  size;
    bool    is_attached;
};

#ifdef aa
/**
 * @brief create string
 * @param len reserve len
 * @return new string
 *
 * totaol space: len + 1
 */
ax_string* ax_string_create(size_t len)
{
    if(0 == len)
        len = 100;

    ax_string* s = ALLOC(ax_string);
    ax_check_and_return_zero(s, NULL);

    s->data = ax_vector_create(len+1, 0);
    s->data_attached = NULL;
    s->size_attached = 0;

    if(NULL == s->data)
    {
        FREE(s);
        return NULL;
    }

    ax_vector_reserve(s->data, len+1);

    return s;
}

void ax_string_destory(ax_string* s)
{
    ax_check_and_return(s, NULL);
    if(s->data)
    {
        ax_vector_destory(s->data);
    }
}

/**
 * @brief copy a string
 * @param other C str alloc outside
 * @return new string
 */
ax_string* ax_string_copy(const char* other)
{
    ax_check_and_return_zero(other, NULL);
    return ax_string_create(strlen(other));
}

/**
 * @brief create string base on buf
 * @param buf          buffer allocate outside
 * @param buf_size     buffer size
 * @return  new string
 *
 * string len: buf_size-1
 * last pos store '\0'
 * when attach, string size can not change!!!
 */
ax_string* ax_string_attach_buf(char* buf, size_t buf_size)
{
    ax_check_and_return_zero(buf && buf_size>0, NULL);
    ax_string* str = ALLOC(ax_string);
    ax_check_and_return_zero(str, NULL);

    str->data = NULL;
    str->data_attached = buf;
    str->size_attached = buf_size;

    return str;
}

/**
 * @brief create string base on C String
 * @param buf
 * @return
 */
ax_string* ax_string_attach(char* str)
{
   return ax_string_attach_buf(str, strlen(str)+1);
}







size_t ax_string_reserve(ax_string *s, size_t size)
{
    ax_check_and_return_zero(s, NULL);
    if(s->data)
    {
       return ax_vector_reserve(s->data, size);
    }
    else
    {
        return s->size_attached;
    }
}


/**
 * @brief append a char
 * @param s
 * @param c
 * @return new string size
 */
size_t ax_string_append(ax_string *s, char c)
{

}

#endif

/**
 * @brief ax_format
 * @param format
 * @return new b    uffer, need free
 * very slow, but convenient
 */
char* ax_format(const char* format, ...)
{
    char buf[MAX_FORMAT_BUFFER];
    size_t len;
    va_list list;
    va_start(list, format);
    len = vsnprintf(buf, sizeof(buf)-1, format, list);
    va_end(list);

    char* ret = ALLOCN(char, len+1);
    return strncpy(ret, buf, len);
}

/**
 * @brief ax_format1
 * @param format
 * @return internal buffer, not safe
 */
char *ax_format1(const char *format, ...)
{
    static char buf[MAX_FORMAT_BUFFER] = {0};
    va_list list;
    va_start(list, format);
    vsnprintf(buf, sizeof(buf)-1, format, list);
    va_end(list);
    return buf;
}

/**
 * @brief ax_format2
 * @param format
 * @return internal buffer, not safe
 */
char *ax_format2(const char *format, ...)
{
    static char buf[MAX_FORMAT_BUFFER] = {0};
    va_list list;
    va_start(list, format);
    vsnprintf(buf, sizeof(buf)-1, format, list);
    va_end(list);
    return buf;
}

enum
{
    SPLIT_STATE_CHECK,
    SPLIT_STATE_MATCHING
};
/**
 * @brief ax_split
 * @param str
 * @param sep
 * @return
 */
ax_list *ax_split(const char *str, const char *sep)
{
    ax_check_and_return_zero(str && sep, NULL);
    ax_vector* buf = ax_vector_create(100, 0);
    ax_list*   list= ax_list_create();
    char* end   = (char*)str + strlen(str);
    char* it = (char*)str;
    int state = SPLIT_STATE_CHECK;
    size_t sep_size  = strlen(sep);
    size_t sep_index = 0;
    while(it != end)
    {
        switch(state)
        {
        case SPLIT_STATE_CHECK:
        {
            if(*it == *sep)
            {
                state = SPLIT_STATE_MATCHING;
            }
            else
            {
                //ax_vector_push_back()
            }
        }
        break;
        case SPLIT_STATE_MATCHING:
            break;
        default:
            ax_error("oh no!!!\n");
        }
    }
    ax_vector_destory(buf);
    return list;
}
